package com.edison.demo.until;

import com.edison.demo.enums.BankCardTypeEnum;
import com.edison.demo.enums.BankNameEnum;
import com.edison.demo.exception.BizException;
import org.apache.commons.lang3.StringUtils;

import java.util.Random;

/**
 * @author edison
 */
public class BankCardNumberGenerator {

    private BankCardNumberGenerator() {
        throw new IllegalStateException("Utility class");
    }
    private static final Random RANDOM = new Random();


    public static String generate() {


        Integer prev = 622126 + RANDOM.nextInt(925 + 1 - 126);
        return generateByPrefix(prev);
    }
    /**
     * <pre>
     * Generates a card number based on the given first six digits.
     * </pre>
     */
    public static String generateByPrefix(Integer prefix) {
        Random random = new Random(System.currentTimeMillis());
        String bardNo = prefix
                + StringUtils.leftPad(random.nextInt(999999999) + "", 9, "0");

        char[] chs = bardNo.trim().toCharArray();
        int luhnSum = LuhnUtils.getLuhnSum(chs);
        char checkCode = luhnSum % 10 == 0 ? '0' : (char) (10 - luhnSum % 10 + '0');
        return bardNo + checkCode;
    }

    /**
     * Generates a corresponding card number based on the bank name and card type.
     *
     * @param bankName the name of the bank
     * @param cardType the type of bank card
     * @return the generated bank card number
     */
    public static String generate(BankNameEnum bankName, BankCardTypeEnum cardType) throws BizException {
        Integer[] candidatePrefixes = null;
        if (cardType == null) {
            candidatePrefixes = bankName.getAllCardPrefixes();
        } else {
            switch (cardType) {
                case DEBIT:
                    candidatePrefixes = bankName.getDebitCardPrefixes();
                    break;
                case CREDIT:
                    candidatePrefixes = bankName.getCreditCardPrefixes();
                    break;
                default:
            }
        }

        if (candidatePrefixes == null || candidatePrefixes.length == 0) {
            throw new BizException("No card information available for the specified bank.");
        }

        Integer prefix = candidatePrefixes[RANDOM.nextInt(candidatePrefixes.length)];
        return generateByPrefix(prefix);
    }
}
